package com.enjoyor.soa.traffic.frame.aop;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
//import com.google.gson.Gson;
//import com.google.gson.GsonBuilder;

@Aspect
@Component
public class WebApiInterceptor {

    private static final Logger logger = Logger.getLogger(WebApiInterceptor.class);
    private String methodInfo;
    private long startTime;
    private long endTime;

    @Pointcut("(execution(* com.enjoyor.soa.traffic.rest.**.controller..*(..)))")
    public void webApiMethodPointcut() {
    }

    @Before("webApiMethodPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        this.startTime = System.currentTimeMillis();
        String methodInfo = "";
        Class<?> targetClass = joinPoint.getTarget().getClass();
        String className = targetClass.getName();
        methodInfo = methodInfo + className;

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();
        methodInfo = methodInfo + "." + methodName;

        String[] parameterNames = signature.getParameterNames();
        methodInfo = methodInfo + "(";
        for (String parameterName : parameterNames) {
            if (methodInfo.endsWith("(")) {
                methodInfo = methodInfo + parameterName;
            } else {
                methodInfo = methodInfo + "," + parameterName;
            }
        }
        methodInfo = methodInfo + ")";
        this.methodInfo = methodInfo;

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();

        String requestUrl = request.getRequestURL().toString();
        String requestMethod = request.getMethod();
        String queryString = request.getQueryString();

        logger.info(String.format("WebApi start, method: {%s}", new Object[] { this.methodInfo }));

        logger.info(String.format("WebApi request, url: {%s}, method: {%s},  params: {%s}",
                new Object[] { requestUrl, requestMethod, queryString }));

    }

    @AfterThrowing(pointcut = "webApiMethodPointcut()", throwing = "e")
    public void doAfterThrowing(JoinPoint point, Throwable e) {
        logger.error(String.format("WebApi exception, method: {%s}, msg: {%s}", new Object[] { this.methodInfo, e }));
    }

    @AfterReturning(value = "webApiMethodPointcut()", argNames = "rtv", returning = "rtv")
    public void afterInsertMethod(JoinPoint jp, Object rtv) throws Throwable {
        // Gson gson = new
        // GsonBuilder().serializeSpecialFloatingPointValues().create();
        logger.info(String.format("WebApi result: %s", new Object[] { JSON.toJSONString(rtv) }));
    }

    @After(value = "webApiMethodPointcut()")
    public void after(JoinPoint joinPoint) {
        this.endTime = System.currentTimeMillis();
        long costMs = this.endTime - this.startTime;
        logger.info(String.format("WebApi end, method: {%s}, time: {%s}ms",
                new Object[] { this.methodInfo, Long.valueOf(costMs) }));
    }

}
